<!--
 * @Description: In User Settings Edit
 * @Author: your name
 * @Date: 2019-08-12 12:04:39
 * @LastEditTime: 2020-04-09 15:53:33
 * @LastEditors: Please set LastEditors
 -->
<template>
  <div @touchstart="touchStart($event)" @touchmove="touchMove($event)" @touchend="touchEnd($event)">
    <div class="pull-refresh" :style="{opacity:(this.touching||this.state>0)?1:0}" v-show="enableRefresh">
      <span class="down-tip" v-show="state==0 ">下拉更新</span>
      <span class="up-tip" v-show="state==1 ">松开刷新数据</span>
      <div class="refresh-tip" v-show="state==2">
        <img src="/images/loading.gif" width="50" height="50">
        <span class="refresh-tip">加载中…</span>
      </div>
    </div>
    <div :style="{background:'white',top:top+'px'} " id="listcontentdiv">
      <slot name="list"></slot>
    </div>
  </div>
</template>
<style scoped>
  .pull-refresh {
    background: #eeeeee;
    position: absolute;
    height: 50%;
    width: 100%;
    text-align: center;
    padding-top: 30px;
  }
  .refresh-tip {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
  }
</style>
<script>
  import bus from '@/common/bus'
  import { apiConstants } from '@/js/utils';
  import { isBottom } from '@/js/utils'
  export default {
    props: {
      api: {
        type: Object,
        required: true
      },
      params: {
        type: Object,
        default() {
          return {}
        }
      },
      //设置显示的top ，如果top为 0 ，则显示  查看更多，下拉刷新，大于0则不显示
      showTop: {
        type: Number,
        default: 0
      },
      event: {  // 请求到数据事件名
        type: String,
        default: 'more'
      },
      resList: {  // 请求返回值的 list 名字
        type: String,
        default: ''
      },
      enableRefresh: {//是否支持下拉刷新
        type: Boolean,
        required: false
      }
    },
    data() {
      return {
        offset: 100,
        state: 0,//0表示滑动距离不足触发刷新，1表示滑动距离可以触发刷新，等待松手后刷新，2表示正在刷新数据
        pageNo: 1,
        ctrl: false, // 不可请求为 true
        top: 0,
        touching: false,
        loading: false
      }
    },
    watch: {
      touching() {
        debugger;
        if (this.touching) {
          document.getElementById("listcontentdiv").style.minHeight = document.getElementsByClassName("pull-refresh")[0].offsetHeight + "px";
        } else if (this.state == 0) {
          document.getElementById("listcontentdiv").style.minHeight = "";
        }
      },
      state() {
        if (this.state == 0) {
          document.getElementById("listcontentdiv").style.minHeight = "";
        }
      },


    },
    created() {
      debugger;
      this.$Toast.start();
      this.$LoadingBar.finish();
      this.requestData(this.initCallback);

    },
    mounted() {
      // 初始化列表滚动请求更多事件
      document.addEventListener('scroll', this.moreData, false)
    },
    beforeDestroy() {
      document.removeEventListener('scroll', this.moreData)
    },
    methods: {

      requestData(cb) {
        // 测试用
        if (!this.api) {
          setTimeout(() => {
            bus.$emit(this.event, new Array(10))
            this.$Toast.finish()
          }, 100)
          return
        }
        if (this.pageNo == 0) {
          this.pageNo = 1;
          bus.$emit("clearlist");

        }
        this.params.pageNo = this.pageNo
        this.getData(cb);


      },
      getData(cb) {
        debugger;
        if (!this.loading) {
          this.loading = true;
          Vue.prototype.$ajax(this.api, {
            data: this.params,
            isJson: this.api.method.toLowerCase() == "get",
            success: res => {
              if (this.state === 2) {//如果是下拉刷新，需要先发清空list的通知K
                bus.$emit("clearlist");
              }
              bus.$emit(this.event, res || null);
              this.loading = false;
              this.resList ? cb(res[this.resList]) : cb(res)  // 提示是否有更多数据
            },
            error: res => {
              this.loading = false;
              this.$LoadingBar.error();
            },
            fail: res => {
              this.$LoadingBar.error();
              this.loading = false;
            },
            closeToast: true
          })
        }

      },
      // 滚动到底部请求更多
      moreData() {
        if (this.pageNo == 1) {
          //清空数据
          bus.$emit("clearlist");
        }
        if (isBottom()) {
          if (this.ctrl || this.state === 2 || this.showTop > 0 || this.loading) return
          this.ctrl = true
          this.$LoadingBar.start()
          this.requestData(this.moreCallback)
        }
        if (this.enableRefresh && !this.touching) {
          //TODO:手机端用力划一下，一直滚动，会出现滚动到顶部以上的情况，如果这个时候需要触发下拉刷新，则在这里加代码
          //如果window.scrollY小于0，就可以写下拉刷新的逻辑
        }
      },

      // 初始化列表回调
      initCallback(res) {
        this.pageNo++
        this.$Toast.finish();


      },

      // 更多列表回调
      moreCallback(data) {
        if (data.listInfo != undefined) {
          data = data.listInfo;
        }
        if (!data || !data.length) {  // 没有数据了
          this.$LoadingBar.end()
          return
        }
        this.ctrl = false  // 只有后面有数据才可请求下一页
        this.pageNo++
        this.$LoadingBar.finish()
      },

      touchStart(e) {
        this.startY = e.targetTouches[0].pageY;
        this.startScroll = window.scrollY || 0;
        this.touching = true; //留着有用，不能删除
      },
      touchMove(e) {
        if (!this.enableRefresh || !this.touching) {
          return
        }
        let diff = e.targetTouches[0].pageY - this.startY - this.startScroll
        if (diff > 0) e.preventDefault()
        this.top = Math.pow(diff, 0.8) + (this.state === 2 ? this.offset : 0)
        if (this.state === 2) { // in refreshing
          return
        }
        if (this.top >= this.offset) {
          this.state = 1;
        } else {
          this.state = 0
        }
      },
      touchEnd(e) {
        if (!this.enableRefresh) {
          return
        }
        if (this.state === 2) { // 正在刷新，只是将滑动位置调整，不再触发刷新函数
          this.state = 2
          this.top = this.offset
          return
        }
        if (this.state === 1) { // 已经达到触发刷新的滑动距离，将状态变为刷新中，然后触发刷新函数
          this.refresh()
        } else { // 没达到距离，取消刷新
          this.state = 0
          this.top = 0
        }
        this.touching = false

      },
      refresh() {
        this.state = 2;
        this.top = this.offset;
        this.pageNo = 1;
        setTimeout(() => {
          this.requestData(this.refreshDone)
        }, 300);
      },
      refreshDone() {
        this.initCallback();
        this.state = 0;
        this.top = 0;
        this.$LoadingBar.finish();
        this.ctrl = false;
      }
    }
  }
</script>

